#include "raylib.h"
#include "raymath.h" // For PI, RAD2DEG, Vector2 functions if needed
#include <stdio.h>   // For sprintf in older C, though TextFormat is preferred
#include <math.h>    // For sqrtf, atan2f

// Function to draw a grid aligned with the Cartesian origin
void DrawCartesianGrid(Vector2 origin, int spacing, int screenWidth, int screenHeight, Color color) {
    // Vertical lines
    for (float x = origin.x; x < screenWidth; x += spacing) DrawLine(x, 0, x, screenHeight, color); // Right side
    for (float x = origin.x - spacing; x > 0; x -= spacing) DrawLine(x, 0, x, screenHeight, color); // Left side
    // Horizontal lines
    for (float y = origin.y; y < screenHeight; y += spacing) DrawLine(0, y, screenWidth, y, color); // Bottom side
    for (float y = origin.y - spacing; y > 0; y -= spacing) DrawLine(0, y, screenWidth, y, color); // Top side
}

int main(void) {
    // Initialization
    const int screenWidth = 800;
    const int screenHeight = 600;

    InitWindow(screenWidth, screenHeight, "Coordinate Systems Demo - Cartesian & Polar");

    Font customFont = GetFontDefault(); // Initialize with default font
    // Attempt to load a custom font. Replace "arial.ttf" with your font file.
    // Make sure the font file is accessible (e.g., in the same directory as the executable or provide a full path).
    Font loadedFont = LoadFont("resources/arial.ttf"); // <--- 修改这里
    if (loadedFont.texture.id != 0) { // Check if font loaded successfully
        customFont = loadedFont;
    } else {
        // Optional: Log an error if font loading fails
        TraceLog(LOG_WARNING, "Failed to load custom font, using default.");
    }


    Vector2 origin = { (float)screenWidth / 2, (float)screenHeight / 2 };
    Vector2 pointScreen = { 0, 0 }; // Point in screen coordinates
    Vector2 pointCartesian = { 0, 0 }; // Point in Cartesian coordinates (relative to origin)
    
    float polarR = 0.0f;
    float polarThetaRad = 0.0f; // Angle in radians
    float polarThetaDeg = 0.0f; // Angle in degrees

    bool pointSelected = false;
    int gridSpacing = 20;

    SetTargetFPS(60);

    // Main game loop
    while (!WindowShouldClose()) {
        // Update
        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) {
            pointScreen = GetMousePosition();
            pointSelected = true;

            // Convert screen coordinates to Cartesian coordinates
            // X increases to the right (same as screen)
            // Y increases upwards (opposite to screen Y)
            pointCartesian.x = pointScreen.x - origin.x;
            pointCartesian.y = origin.y - pointScreen.y; 

            // Calculate Polar coordinates
            polarR = sqrtf(pointCartesian.x * pointCartesian.x + pointCartesian.y * pointCartesian.y);
            polarThetaRad = atan2f(pointCartesian.y, pointCartesian.x); // atan2f handles quadrants correctly, returns radians
            polarThetaDeg = polarThetaRad * RAD2DEG; // Convert radians to degrees
            
            // Normalize degrees to [0, 360) for consistent arc drawing if needed,
            // but Raylib's DrawCircleSectorLines should handle negative angles for CW.
            // If issues arise with arc drawing for negative angles, uncomment:
            if (polarThetaDeg < 0) polarThetaDeg += 360.0f;
        }

        // Draw
        BeginDrawing();
        ClearBackground(RAYWHITE);

        // Draw grid
        DrawCartesianGrid(origin, gridSpacing, screenWidth, screenHeight, LIGHTGRAY);

        // Draw Cartesian Axes
        DrawLine(0, origin.y, screenWidth, origin.y, BLACK); // X-axis
        DrawLine(origin.x, 0, origin.x, screenHeight, BLACK); // Y-axis
        DrawText("X", screenWidth - 25, origin.y + 5, 20, BLACK);
        DrawText("Y", origin.x + 5, 10, 20, BLACK);
        DrawText("O", origin.x - 15, origin.y + 5, 15, BLACK); // Origin marker

        if (pointSelected) {
            // Draw the point
            DrawCircleV(pointScreen, 6, MAROON);

            // Draw radius line (r)
            DrawLineEx(origin, pointScreen, 2.0f, BLUE);

            // Draw angle arc (theta)
            // 注意raylib自带的绘制函数是顺时针的，导致AI自动生成的代码不可用，需要调整
            //DrawCircleSectorLines(origin, 40, 0, polarThetaDeg, 30, LIME);            
            DrawCircleSectorLines(origin, 40, 360.0f-polarThetaDeg, 360.0f, 30, LIME);
            
            // Display coordinates
            const char *cartText = TextFormat("Cartesian: (%.1f, %.1f)", pointCartesian.x, pointCartesian.y);
            // Use DrawTextEx with the custom font if it was loaded successfully
            DrawTextEx(customFont, cartText, (Vector2){10, 10}, 20, 1, DARKBLUE);


            const char *polarText = TextFormat("Polar: (r = %.1f, theta = %.2f rad / %.1f deg)", polarR, polarThetaRad, polarThetaDeg);
            // Using \xCE\xB8 for theta symbol (θ) in UTF-8
            // Use DrawTextEx with the custom font
            DrawTextEx(customFont, polarText, (Vector2){10, 40}, 20, 1, DARKPURPLE); // Assuming spacing 1 for custom font
            
            // Draw labels for r and theta on the graph
            Vector2 midRadius = Vector2Lerp(origin, pointScreen, 0.5f);
            DrawTextEx(customFont, "r", (Vector2){midRadius.x + 5, midRadius.y}, 20, 1, BLUE);
            
            // Position theta label near the arc
            float arcLabelRadius = 60; // A bit outside the drawn arc
            Vector2 thetaLabelPos = {
                origin.x + arcLabelRadius * cosf(polarThetaRad / 2), // Mid-angle for label
                origin.y - arcLabelRadius * sinf(polarThetaRad / 2)  // Screen Y is inverted
            };
            // Use DrawTextEx with the custom font for the theta symbol
            DrawTextEx(customFont, "theta", thetaLabelPos, 20, 1, GREEN);

        } else {
            // Use DrawTextEx with the custom font if it was loaded successfully
            DrawTextEx(customFont, "Click and drag mouse to set a point", (Vector2){10, 10}, 20, 1, DARKGRAY);
        }
        
        DrawFPS(screenWidth - 100, 10);

        EndDrawing();
    }

    // De-Initialization
    if (customFont.texture.id != GetFontDefault().texture.id) { // Unload only if a custom font was loaded
        UnloadFont(customFont);
    }
    CloseWindow();

    return 0;
}